package com.tencent.sr.iris.activity.service.event.job;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.tencent.sr.bizmid.user.core.interfaces.dto.UserCoreDTO;
import com.tencent.sr.iris.activity.common.config.IrisThreadPoolConfig;
import com.tencent.sr.iris.activity.common.enums.*;
import com.tencent.sr.iris.activity.common.util.ShardingIdUtil;
import com.tencent.sr.iris.activity.common.util.TimeUtils;
import com.tencent.sr.iris.activity.dependency.qufa.GroupTaskDependency;
import com.tencent.sr.iris.activity.dependency.user.UserCoreDependency;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityCheckResultDTO;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityDTO;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityTaskDTO;
import com.tencent.sr.iris.activity.interfaces.dto.AwardInfoDTO;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityTaskIdEnum;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityTypeEnum;
import com.tencent.sr.iris.activity.interfaces.event.dto.ActivityEventDTO;
import com.tencent.sr.iris.activity.interfaces.request.task.AllUserRequest;
import com.tencent.sr.iris.activity.interfaces.response.activity.QueryAwardReceiveListResponse;
import com.tencent.sr.iris.activity.interfaces.response.group.task.AllUserRes;
import com.tencent.sr.iris.activity.repository.entity.TIrisActivityAwardRecordDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisActivityTaskDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskBatchDataDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskRecordDO;
import com.tencent.sr.iris.activity.repository.mapper.TIrisActivityAwardRecordMapper;
import com.tencent.sr.iris.activity.repository.mapper.TIrisUserTaskRecordMapper;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisActivityAwardRecordExample;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisUserTaskRecordExample;
import com.tencent.sr.iris.activity.repository.singlemapper.TIrisActivityTaskMapper;
import com.tencent.sr.iris.activity.repository.singlemapper.TIrisUserTaskBatchDataMapper;
import com.tencent.sr.iris.activity.repository.singlemapper.example.TIrisActivityTaskExample;
import com.tencent.sr.iris.activity.repository.singlemapper.example.TIrisUserTaskBatchDataExample;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityTaskService;
import com.tencent.sr.iris.activity.service.config.ActivityConfig;
import com.tencent.sr.iris.activity.service.config.TaskBatchDataConfig;
import com.tencent.sr.iris.activity.service.event.activity.*;
import com.tencent.sr.iris.activity.service.event.task.IrisInviteCommissionTaskExecutor;
import com.tencent.sr.iris.activity.service.event.util.ActivityCommonUtilService;
import com.tencent.sr.iris.activity.service.event.vo.TIrisUserTaskBatchDataVO;
import com.tencent.sr.iris.activity.service.util.BeanConvertUtil;
import com.tencent.sr.iris.user.core.service.interfaces.dto.tutor.UserTutorRelationDTO;
import com.tencent.sr.iris.user.core.service.interfaces.dto.user.UserWideDTO;
import com.tencent.sr.iris.user.core.service.interfaces.enums.LeaderTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SpecialInviteResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SupervisorRelationResponse;
import com.tencent.sr.rmall.material.interfaces.enums.EYesNo;
import com.tencent.sr.rmall.springbootstarter.elasticjob.TaskJob;
import com.tencent.sr.rmall.springbootstarter.monitor.util.MonitorUtil;
import com.tencent.sr.rmall.springbootstarter.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 增量跑批数据
 */
@Slf4j
@Component
@TaskJob(jobName = "userActivityTaskBatchDataJobIncrement", cron = "0 0 1 /1 * ? ", description = "用户参与活动增量数据跑批任务")
public class UserActivityTaskBatchDataJobIncrement implements SimpleJob {

    @Resource
    private GroupTaskDependency groupTaskDependency;

    @Resource
    public ActivityConfig activityConfig;

    @Resource
    private IrisActivityService activityService;

    @Resource
    private IrisActivityTaskService activityTaskService;

    @Resource
    private TIrisUserTaskRecordMapper userTaskRecordMapper;

    @Resource
    protected UserCoreDependency userCoreDependency;

    @Resource
    private TIrisActivityAwardRecordMapper activityAwardRecordMapper;

    @Resource
    private TIrisUserTaskBatchDataMapper userTaskBatchDataMapper;

    @Resource
    private IrisMonthGiftActivityExecutor monthGiftActivityExecutor;

    @Resource
    private IrisInviteGiftActivityExecutor inviteGiftActivityExecutor;
    @Resource
    private SpecialIrisInviteGiftActivityExecutor specialIrisInviteGiftActivityExecutor;

    @Resource
    private UserBecomeTraineeActivityExecutor registGiftActivityExecutor;

    @Resource
    private TIrisActivityTaskMapper activityTaskMapper;

    @Resource(name = IrisThreadPoolConfig.IRIS_USER_BATCH_DATA_THREAD_EXECUTOR)
    private ExecutorService batchDataExecutor;

    @Resource
    private TaskBatchDataConfig taskBatchDataConfig;
    @Resource
    private ActivityCommonService activityCommonService;
    @Resource
    private ActivityCommonUtilService activityCommonUtilService;
    @Resource(name = "irisInviteCommissionTaskExecutor")
    private IrisInviteCommissionTaskExecutor inviteCommissionTaskExecutor;
    @Resource
    private RedissonClient redissonClient;

    /**
     * 特邀会员的枚举值
     */
    public static final Integer SPECIAL_CODE = Integer.valueOf(LeaderTypeEnum.SPECIAL_LEADER.getCode());
    /**
     * 非特邀会员的枚举值
     */
    public static final Integer UN_SPECIAL_CODE = Integer.valueOf(LeaderTypeEnum.INVALID.getCode());

    @Override
    public void execute(ShardingContext shardingContext) {
        //获取批次号,任务执行时刻前一天
        LocalDate localDate = LocalDate.now().minusDays(1);
        String batchNo = localDate.format(DateTimeFormatter.ofPattern(TimeUtils.YYYY_MM_DD));
        //批次时间戳
        Long timestamp = localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        log.info("批量生成用户任务参与数据:batchNo={}", batchNo);

        RLock lock = null;
        try {
            lock = redissonClient.getLock(getLockKey());
            if (!lock.tryLock(30, TimeUnit.SECONDS)) {
                log.info("跑批数据任务：有任务正在执行中，本次忽略");
                return;
            }

            //加载需要判断的月月领和邀请有礼活动
            ActivityDTO monthActivity = activityService.getActivity(activityConfig.getMonthGiftActivityId());
            ActivityDTO inviteActivity = activityService.getActivityAllTask(activityConfig.getInviteGiftActivityId());
            ActivityDTO specialInviteActivity = activityService
                    .getActivityAllTask(activityConfig.getSpecialInviteGiftActivityId());
            ActivityDTO registGift = activityService.getActivityAllTask(activityConfig.getRegistGiftActivityId());
            //解析所有任务奖品信息
            Map<String, AwardInfoDTO> taskAwardInfoMap = getAllTaskAwardInfo();
            //升级有礼的活动下所有任务
            List<String> activityIds = Lists
                    .newArrayList(activityConfig.getLevelUpFosterActivityId(),
                            activityConfig.getLevelUpPromoActivityId(),
                            activityConfig.getGuideAllowanceActivityId());
            List<String> taskIds = getActivityTaskIds(activityIds);
            //分页查询全量用户
            int pageNo = 1;
            List<AllUserRes> users;
            int size = 0;

            AllUserRequest request = AllUserRequest.builder().pageNo(pageNo).pageSize(taskBatchDataConfig.getPageSize())
                    .build();
            if (shardingContext != null && StrUtil.isNotBlank(shardingContext.getJobParameter())) {
                String uid = shardingContext.getJobParameter();
                request.setUid(uid);
                log.info("userActivityTaskBatchDataJobIncrement从uid：{}以后开始查询用户", uid);
            }
            while (!taskBatchDataConfig.isBatchDataJobStop()) {
                if (size >= taskBatchDataConfig.getTotalLimit()) {
                    log.info("超出处理数量上限,totalLimit={}", taskBatchDataConfig.getTotalLimit());
                    break;
                }
                //分页查询全量用户
                log.info("分页查询用户req={}", JSONObject.toJSONString(request));
                users = groupTaskDependency.queryAllUsers(request).getDataList();
                log.info("分页查询用户pageNo={},pageSize={},resultCount={}", pageNo, taskBatchDataConfig.getPageSize(),
                        users.size());
                if (CollectionUtils.isEmpty(users)) {
                    log.info("全量用户数据查询完毕");
                    break;
                }
                List<CompletableFuture<List<TIrisUserTaskBatchDataVO>>> features = users.stream().map(user -> {
                    CompletableFuture<List<TIrisUserTaskBatchDataVO>> feature = CompletableFuture.supplyAsync(
                            () -> executeUserTaskData(batchNo, user, monthActivity, inviteActivity,
                                    specialInviteActivity, registGift, taskAwardInfoMap,
                                    timestamp, taskIds),
                            batchDataExecutor);
                    return feature;
                }).collect(Collectors.toList());

                CompletableFuture.allOf(features.toArray(new CompletableFuture[0])).join();

                List<List<TIrisUserTaskBatchDataVO>> batchUserRecordList = features.stream().map(completableFuture -> {
                    List<TIrisUserTaskBatchDataVO> res = null;
                    try {
                        res = completableFuture.get();
                        log.info("用户实际保存记录数量={}", res.size());
                    } catch (Exception e) {
                        log.error("多线程执行，单个用户请求错误 completableFuture:{}",
                                JsonUtils.toJsonString(completableFuture), e);
                    }
                    return res;
                }).collect(Collectors.toList());

                List<TIrisUserTaskBatchDataDO> batchDOList = batchUserRecordList.stream()
                        .flatMap(Collection::stream).collect(Collectors.toList());
                batchUserRecordList.clear();

                try {
                    handleUserInfo(batchDOList);
                    //批量保存用户的任务参与记录
                    int count = batchSaveOrUpdate(batchDOList);
                    log.info("多线程批量执行 dataSize={},save count={}", batchDOList.size(), count);
                    batchDOList.clear();
                } catch (Exception e) {
                    log.error("跑批处理用户信息错误,batchNo=", batchNo, e);
                }

                size += users.size();
                request.setPageNo(++pageNo);
                //设置分页查询用户参数,uid参数为当页处理最大的uid
                request.setUid(users.get(users.size() - 1).getUid());
            }
            log.info("执行完成,batchNo={}，共处理{}个用户", batchNo, size);
        } catch (Exception e) {
            log.error("批量生成用户任务参与数据:执行异常", e);
            MonitorUtil.getSingleMonitorService()
                    .logTransaction("activity_job", "UserActivityTaskBatchDataJob", timestamp, e);
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
    }

    private String getLockKey() {
        return "userActivityTaskBatchDataJobIncrement_lock";
    }

    /**
     * 处理用户信息
     * @param batchDOList
     */
    private void handleUserInfo(List<TIrisUserTaskBatchDataDO> batchDOList) {
        //用户信息
        List<String> uidList = batchDOList.stream().filter(i -> StrUtil.isNotBlank(i.getUid()))
                .map(TIrisUserTaskBatchDataDO::getUid).distinct().collect(Collectors.toList());
        List<String> pidList = batchDOList.stream().filter(i -> StrUtil.isNotBlank(i.getPid()))
                .map(TIrisUserTaskBatchDataDO::getPid).distinct().collect(Collectors.toList());
        List<String> allUid = (List<String>) CollectionUtil.union(uidList, pidList);
        Map<String, UserWideDTO> userInfoMap = activityCommonUtilService.queryUserWideMapCache(allUid);

        //补充每个pid和uid是否特邀的标识
        for (TIrisUserTaskBatchDataDO tIrisUserTaskBatchDataDO : batchDOList) {
            String uid = tIrisUserTaskBatchDataDO.getUid();
            if (!Strings.isNullOrEmpty(uid)) {
                //导师uid
                UserTutorRelationDTO userTutorRelationDTO = activityCommonUtilService.queryUserTutorCache(uid);
                tIrisUserTaskBatchDataDO.setAdvisorUid(
                        Optional.ofNullable(userTutorRelationDTO.getTutorUid()).orElse(StrUtil.EMPTY));

                //下级特邀信息
                SpecialInviteResponse specialInviteResponse = activityCommonUtilService
                        .querySpecialInviteCache(uid);
                boolean uidNotSpecial = !LeaderTypeEnum.SPECIAL_LEADER.getCode()
                        .equals(specialInviteResponse.getTag());
                tIrisUserTaskBatchDataDO.setUidSpecialInvite(uidNotSpecial ? UN_SPECIAL_CODE : SPECIAL_CODE);
                tIrisUserTaskBatchDataDO.setSpecialInviteTime(
                        Optional.ofNullable(specialInviteResponse.getTimeStamp()).map(DateUtil::date)
                                .orElse(null));

                //下级区域
                Long areaId = getAreaId(uid, userInfoMap);
                tIrisUserTaskBatchDataDO.setAreaId(areaId);
            }

            String pid = tIrisUserTaskBatchDataDO.getPid();
            if (!Strings.isNullOrEmpty(pid)) {
                //上级区域
                Long areaId = getAreaId(pid, userInfoMap);
                tIrisUserTaskBatchDataDO.setSuperiorAreaId(areaId);

                //上级特邀信息
                SpecialInviteResponse specialInviteResponse = activityCommonUtilService
                        .querySpecialInviteCache(pid);
                boolean pidNotSpecial = !LeaderTypeEnum.SPECIAL_LEADER.getCode()
                        .equals(specialInviteResponse.getTag());
                tIrisUserTaskBatchDataDO.setPidSpecialInvite(pidNotSpecial ? UN_SPECIAL_CODE : SPECIAL_CODE);
                tIrisUserTaskBatchDataDO.setSuperiorSpecialInviteTime(
                        Optional.ofNullable(specialInviteResponse.getTimeStamp()).map(DateUtil::date)
                                .orElse(null));
            }

        }
    }

    /**
     * 获取区域id
     *
     * @param uid
     * @param userInfoMap
     * @return
     */
    private Long getAreaId(String uid, Map<String, UserWideDTO> userInfoMap) {
        UserWideDTO userInfo = Optional.ofNullable(userInfoMap.get(uid))
                .orElseGet(UserWideDTO::new);
        List<Long> groupChain = userInfo.getGroupChain();
        if (CollectionUtil.isNotEmpty(groupChain) && groupChain.size() >= 2) {
            //groupChain第二个为大区id
            return Optional.ofNullable(groupChain.get(1)).orElse(0l);
        }
        return 0l;
    }

    private void updateUnparticipatedUserTaskStatus(Long batchTimeStamp) {
        //更新月月领邀请有礼未参加且已过期的记录状态为未完成
        TIrisUserTaskBatchDataExample monthExample = new TIrisUserTaskBatchDataExample();
        //参与状态=未参与,任务状态=进行中,任务结束时间<=批次时间
        monthExample.createCriteria().andPropertyIn(TIrisUserTaskBatchDataExample.ACTIVITY_TYPE,
                Lists.newArrayList(ActivityTypeEnum.MONTH_GIFT.getCode(), ActivityTypeEnum.INVITE_GIFT.getCode()))
                .andPropertyEqualTo(TIrisUserTaskBatchDataExample.IS_PARTICIPATED, TaskBatchDateIsParticipatedEnum.NO)
                .andPropertyEqualTo(TIrisUserTaskBatchDataExample.USER_TASK_STATUS,
                        UserTaskStatusEnum.PROGRESS.getCode())
                .andPropertyLessThan(TIrisUserTaskBatchDataExample.CURRENT_TASK_END_TIME, new Date(batchTimeStamp));
        TIrisUserTaskBatchDataDO userTaskBatchDataDO = new TIrisUserTaskBatchDataDO();
        userTaskBatchDataDO.setUserTaskStatus(UserTaskStatusEnum.UNFINISHED.getCode());
        int res = userTaskBatchDataMapper.updateByExampleSelective(userTaskBatchDataDO, monthExample);
        log.info("更新未参与跑批记录状态为未完成,resCount={}", res);
    }


    private List<String> getActivityTaskIds(List<String> activityIds) {
        TIrisActivityTaskExample example = new TIrisActivityTaskExample();
        example.createCriteria().andPropertyIn(TIrisActivityTaskExample.ACTIVITY_ID, activityIds);
        List<TIrisActivityTaskDO> tIrisActivityTaskDOS = activityTaskMapper.selectByExample(example);
        return tIrisActivityTaskDOS.stream().map(TIrisActivityTaskDO::getBizId).collect(Collectors.toList());
    }

    private int batchSaveOrUpdate(List<TIrisUserTaskBatchDataDO> userTaskBatchDataDOS) {
        if (!CollectionUtils.isEmpty(userTaskBatchDataDOS)) {
            log.info("批量入库用户任务参与数据,count={}", userTaskBatchDataDOS.size());
            int res = userTaskBatchDataMapper.batchInsertIgnoreSelective(userTaskBatchDataDOS);
            log.info("批量入库用户任务参与数据,count={},resultCount={}", userTaskBatchDataDOS.size(), res);
            return res;
        }
        return 0;
    }

    private Map<String, AwardInfoDTO> getAllTaskAwardInfo() {
        Map<String, AwardInfoDTO> awardInfoDTOMap = new HashMap<>();
        log.info("加载所有任务的奖品信息");
        List<TIrisActivityTaskDO> tIrisActivityTaskDOS = activityTaskService.getAll();
        tIrisActivityTaskDOS.forEach(taskDO -> {
            String awardInfo = taskDO.getAwardInfo();
            AwardInfoDTO awardInfoDTO = activityCommonService.getAwardInfoCacheByMarket(awardInfo);
            awardInfoDTOMap.put(taskDO.getBizId(), awardInfoDTO);
        });
        log.info("任务奖品信息,awardInfoMap={}", JSONObject.toJSONString(awardInfoDTOMap));
        return awardInfoDTOMap;
    }

    /**
     * 执行用户任务
     *
     * @param user
     * @param monthActivity
     * @param inviteActivity
     * @param taskAwardInfoMap
     */
    private List<TIrisUserTaskBatchDataVO> executeUserTaskData(String batchNo, AllUserRes user,
            ActivityDTO monthActivity,
            ActivityDTO inviteActivity,
            ActivityDTO specialInviteActivity,
            ActivityDTO registGift,
            Map<String, AwardInfoDTO> taskAwardInfoMap,
            Long timestamp, List<String> taskIds) {
        List<TIrisUserTaskBatchDataVO> userTaskBatchDataVOS = Lists.newArrayListWithCapacity(20);
        try {
            //查询用户昵称
            UserCoreDTO res = userCoreDependency.queryUserCoreInfo(user.getUid());
            String nickName = res.getNickName();
            log.info("查询用户昵称,uid={},nickname={}", user.getUid(), nickName);
            //查询用户成为见习会员时间
            Long traineeTime = activityCommonService.queryTraineeTime(user.getUid());

            Date traineeTimeDate = Objects.isNull(traineeTime) ? null : new Date(traineeTime);
            //查询用户PID
            SupervisorRelationResponse response = userCoreDependency.queryUserSupervisor(user.getUid());
            String pid = response == null ? "" : response.getParentUid();

            //处理月月领活动任务
            log.info("处理月月领活动,uid={}", user.getUid());
            handleMonthGiftTaskData(batchNo, nickName, traineeTimeDate, user.getUid(), pid, userTaskBatchDataVOS,
                    taskAwardInfoMap, monthActivity,
                    timestamp);
            //处理邀请有礼活动任务
            log.info("处理邀请有礼活动,uid={}", user.getUid());
            handleInviteGiftTaskData(batchNo, nickName, traineeTimeDate, user.getUid(), pid, userTaskBatchDataVOS,
                    taskAwardInfoMap, inviteActivity, timestamp);

            //处理特邀邀请有礼活动任务
            log.info("处理特邀邀请有礼活动,uid={}", user.getUid());
            handleSpecialInviteGiftTaskData(batchNo, nickName, traineeTimeDate, user.getUid(), pid,
                    userTaskBatchDataVOS,
                    taskAwardInfoMap, specialInviteActivity, timestamp);

            //处理注册有礼活动
            handleRegistGiftTaskData(batchNo, nickName, traineeTimeDate, user.getUid(), pid, userTaskBatchDataVOS,
                    taskAwardInfoMap, registGift, timestamp);

            //处理其他活动任务
            log.info("处理其他活动,uid={}", user.getUid());
            handleOtherTaskData(batchNo, nickName, traineeTimeDate, user.getUid(), userTaskBatchDataVOS,
                    taskAwardInfoMap, taskIds);
        } catch (Exception e) {
            log.error("跑批用户处理异常,uid={},errorMsg={}", user.getUid(), e.getMessage(), e);
        }
        return userTaskBatchDataVOS;
    }

    /**
     * 处理月月领任务参与数据,周期类型,单独处理参与数据入库逻辑
     *
     * @param batchNo
     * @param nickName
     * @param traineeTimeDate
     * @param uid
     * @param taskAwardInfoMap
     * @param monthActivity
     * @param timestamp
     */
    private void handleMonthGiftTaskData(String batchNo, String nickName, Date traineeTimeDate, String uid, String pid,
            List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS, Map<String, AwardInfoDTO> taskAwardInfoMap,
            ActivityDTO monthActivity, Long timestamp) {
        //查询用户当前周期下，多阶任务是否已经有任务进度
        String period = batchNo.substring(0, 7);
        //查询当前用户月月领的所有参与记录
        TIrisUserTaskRecordExample taskRecordExample = new TIrisUserTaskRecordExample();
        taskRecordExample.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.ACTIVITY_ID, monthActivity.getBizId())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        List<TIrisUserTaskRecordDO> userTaskRecordDOS = userTaskRecordMapper.selectByExample(taskRecordExample);
        userTaskRecordDOS.forEach(t -> userTaskBatchDataDOS
                .add(convertRecordDO2BatchDataDO(batchNo, nickName, traineeTimeDate, t, taskAwardInfoMap)));

        //已经参与的进度记录集合 taskId+taskPeriod
        Set<String> record = userTaskRecordDOS.stream().map(t -> t.getTaskId() + t.getTaskPeriod()).collect(
                Collectors.toSet());

        //活动下每个任务遍历处理，每个任务都得进行准入校验,并记录相关信息
        monthActivity.getActivityTaskDTOS().forEach(task -> {
            if (!record.contains(task.getBizId() + period)) {
                //该任务当前周期下用户没有参与进度记录
                if (timestamp < task.getStartTime().getTime() || timestamp > task.getEndTime().getTime()) {
                    log.info("当前批次处理时间超出任务时间范围,batchNo={}taskBizId:{},currentTime={},startTime={},endTime={}", batchNo,
                            task.getBizId(), timestamp, task.getStartTime(), task.getEndTime());
                    return;
                }
                //当前周期用户没有任务进度记录,检查该用户是否可以参加活动任务
                ActivityCheckResultDTO checkResultDTO = getCheckResultDTO(pid, uid, timestamp, monthActivity,
                        monthGiftActivityExecutor);
                //新构建用户记录数据
                userTaskBatchDataDOS
                        .add(buildUserTaskBatchDataDOS(monthActivity, task, batchNo, nickName, traineeTimeDate, uid,
                                pid,
                                taskAwardInfoMap, checkResultDTO, period, timestamp));
            }
        });
    }

    /**
     * 处理券奖品信息
     *
     * @param userTaskBatchDataDOS
     */
    private void handleAwardReceiveInfo(List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS) {
        if (CollectionUtil.isEmpty(userTaskBatchDataDOS)) {
            return;
        }

        List<String> outOrderList = userTaskBatchDataDOS.stream()
                .filter(i -> StrUtil.isNotBlank(i.getOutTradeNo())).map(TIrisUserTaskBatchDataVO::getOutTradeNo)
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(outOrderList)) {
            return;
        }

        List<QueryAwardReceiveListResponse> awardReceiveList = activityCommonService
                .queryAwardReceiveList(outOrderList);
        Map<String, QueryAwardReceiveListResponse> map = awardReceiveList.stream()
                .collect(Collectors.toMap(QueryAwardReceiveListResponse::getOutTradeNo, i -> i, (i1, i2) -> i1));
        for (TIrisUserTaskBatchDataVO batchDataDO : userTaskBatchDataDOS) {
            String outTradeNo = batchDataDO.getOutTradeNo();
            if (StrUtil.isNotBlank(outTradeNo) && map.containsKey(outTradeNo)) {
                QueryAwardReceiveListResponse awardResponse = Optional.ofNullable(map.get(outTradeNo))
                        .orElseGet(QueryAwardReceiveListResponse::new);
                //券领取时间，核销时间
                batchDataDO.setConsumeTime(awardResponse.getConsumeTime());
                batchDataDO.setAwardRecordTime(awardResponse.getAwardRecordTime());
            }
        }
    }

    /**
     * 处理邀请有礼参与数据,按批次新增记录即可,统一批量入库
     *
     * @param batchNo
     * @param nickName
     * @param traineeTimeDate
     * @param uid
     * @param userTaskBatchDataDOS
     * @param taskAwardInfoMap
     * @param inviteActivity
     * @param timestamp
     */
    private void handleInviteGiftTaskData(String batchNo, String nickName, Date traineeTimeDate, String uid, String pid,
            List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS, Map<String, AwardInfoDTO> taskAwardInfoMap,
            ActivityDTO inviteActivity, Long timestamp) {
        //查询用户是否已经有邀请有礼活动的任务进度记录
        TIrisUserTaskRecordExample taskRecordExample = new TIrisUserTaskRecordExample();
        taskRecordExample.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.ACTIVITY_ID, inviteActivity.getBizId())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        List<TIrisUserTaskRecordDO> userTaskRecordDOS = userTaskRecordMapper.selectByExample(taskRecordExample);
        if (CollectionUtils.isEmpty(userTaskRecordDOS)) {
            if (traineeTimeDate == null) {
                log.info("未查询到见习会员时间,跑批不记录该用户邀请有礼活动参与记录batchNo={},uid={}", batchNo, uid);
                return;
            }
            //没有参与过邀请有礼
            inviteActivity.getActivityTaskDTOS().forEach(task -> {
                //新构建用户记录数据
                if (traineeTimeDate.before(task.getStartTime()) || traineeTimeDate.after(task.getEndTime())) {
                    log.info("用户成为见习会员时间超出任务时间范围,batchNo={}taskBizId:{},traineeTimeDate={},startTime={},endTime={}",
                            batchNo, task.getBizId(), timestamp, task.getStartTime(), task.getEndTime());
                    return;
                }

                //邀请有礼新旧任务切换
                Long changeTime = activityCommonService.queryInviteChangeTime(uid);
                if (Objects.equals(task.getBizId(), ActivityTaskIdEnum.INVITE_GMV_TASK.getCode())
                        && traineeTimeDate.getTime() < changeTime) {
                    log.info("成为见习时间小于注册有礼新任务切换时间，不处理新任务，becomeTraineeTime:{}"
                                    + ",taskBizId:{},traineeTimeDate={},startTime={},endTime={}",
                            traineeTimeDate, task.getBizId(), timestamp, task.getStartTime(), task.getEndTime());
                    return;
                }

                if (!Objects.equals(task.getBizId(), ActivityTaskIdEnum.INVITE_GMV_TASK.getCode())
                        && traineeTimeDate.getTime() >= changeTime) {
                    log.info("成为见习时间大于注册有礼新任务切换时间，不处理旧任务，becomeTraineeTime:{}"
                                    + ",taskBizId:{},traineeTimeDate={},startTime={},endTime={}",
                            traineeTimeDate, task.getBizId(), timestamp, task.getStartTime(), task.getEndTime());
                    return;
                }

                //当前周期用户没有任务进度记录,检查该用户是否可以参加活动任务
                ActivityCheckResultDTO checkResultDTO = getCheckResultDTO(pid, uid, timestamp, inviteActivity,
                        inviteGiftActivityExecutor);

                userTaskBatchDataDOS
                        .add(buildUserTaskBatchDataDOS(inviteActivity, task, batchNo, nickName, traineeTimeDate, uid,
                                pid, taskAwardInfoMap, checkResultDTO, "", timestamp));
            });
        } else {
            //当前用户已经有任务进度记录,直接记录数据
            userTaskRecordDOS.forEach(t -> userTaskBatchDataDOS
                    .add(convertRecordDO2BatchDataDO(batchNo, nickName, traineeTimeDate, t, taskAwardInfoMap)));
        }
    }

    /**
     * 处理特邀邀请有礼参与数据,按批次新增记录即可,统一批量入库
     *
     * @param batchNo
     * @param nickName
     * @param traineeTimeDate
     * @param uid
     * @param userTaskBatchDataDOS
     * @param taskAwardInfoMap
     * @param inviteActivity
     * @param timestamp
     */
    private void handleSpecialInviteGiftTaskData(String batchNo, String nickName, Date traineeTimeDate, String uid,
            String pid,
            List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS, Map<String, AwardInfoDTO> taskAwardInfoMap,
            ActivityDTO inviteActivity, Long timestamp) {
        //查询用户是否已经有邀请有礼活动的任务进度记录
        TIrisUserTaskRecordExample taskRecordExample = new TIrisUserTaskRecordExample();
        taskRecordExample.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.ACTIVITY_ID, inviteActivity.getBizId())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        List<TIrisUserTaskRecordDO> userTaskRecordDOS = userTaskRecordMapper.selectByExample(taskRecordExample);
        if (CollectionUtils.isEmpty(userTaskRecordDOS)) {
            if (traineeTimeDate == null) {
                log.info("未查询到见习会员时间,跑批不记录该用户特邀邀请有礼活动参与记录batchNo={},uid={}", batchNo, uid);
                return;
            }
            //没有参与过邀请有礼
            inviteActivity.getActivityTaskDTOS().forEach(task -> {
                //新构建用户记录数据
                if (traineeTimeDate.before(task.getStartTime()) || traineeTimeDate.after(task.getEndTime())) {
                    log.info("用户成为见习会员时间超出任务时间范围,batchNo={}taskBizId:{},traineeTimeDate={},startTime={},endTime={}",
                            batchNo, task.getBizId(), timestamp, task.getStartTime(), task.getEndTime());
                    return;
                }
                //当前周期用户没有任务进度记录,检查该用户是否可以参加活动任务
                ActivityCheckResultDTO checkResultDTO = getCheckResultDTO(pid, uid, timestamp, inviteActivity,
                        specialIrisInviteGiftActivityExecutor);

                userTaskBatchDataDOS
                        .add(buildUserTaskBatchDataDOS(inviteActivity, task, batchNo, nickName, traineeTimeDate, uid,
                                pid, taskAwardInfoMap, checkResultDTO, "", timestamp));
            });
        } else {
            //当前用户已经有任务进度记录,直接记录数据
            userTaskRecordDOS.forEach(t -> userTaskBatchDataDOS
                    .add(convertRecordDO2BatchDataDO(batchNo, nickName, traineeTimeDate, t, taskAwardInfoMap)));
        }
    }

    /**
     * 获取校验结果
     *
     * @param uid
     * @param timestamp
     * @param activityDTO
     * @param activityExecutor
     * @return
     */
    private ActivityCheckResultDTO getCheckResultDTO(String pid, String uid, Long timestamp, ActivityDTO activityDTO,
            AbstractIrisActivityExecutor activityExecutor) {
        ActivityCheckResultDTO checkResultDTO;
        ActivityEventDTO eventDTO = ActivityEventDTO.builder().uid(uid).pid(pid).eventTime(timestamp).build();
        try {
            checkResultDTO = activityExecutor
                    .doActivityCheck(activityDTO, eventDTO);
            //活动校验成功，再次校验活动的准入条件
            if (checkResultDTO.isSatisfy()) {
                checkResultDTO = activityExecutor
                        .doAccessConditionCheck(activityDTO, eventDTO);
                log.info("跑批校验活动准入条件，校验结果：{}", JSON.toJSONString(checkResultDTO));
            }
        } catch (Exception e) {
            checkResultDTO = ActivityCheckResultDTO.builder().satisfy(false).errorMsg(e.getMessage()).build();
            log.error("跑批校验错误：", e);
        }
        return checkResultDTO;
    }

    /**
     * 邀请有礼是周期任务，周期为一天，跑数只查询最近的一次参与记录
     *
     * @param batchNo
     * @param nickName
     * @param traineeDateTime
     * @param uid
     * @param userTaskBatchDataDOS
     * @param taskAwardInfoMap
     */
    private void handleRegistGiftTaskData(String batchNo, String nickName, Date traineeDateTime, String uid, String pid,
            List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS, Map<String, AwardInfoDTO> taskAwardInfoMap,
            ActivityDTO registGift, Long timestamp) {
        long registGiftEndTime = activityCommonUtilService.getRegistGiftEndTime(uid);
        if (registGiftEndTime < System.currentTimeMillis()) {
            return;
        }
        registGift.getActivityTaskDTOS().forEach(taskDTO -> {
            TIrisUserTaskRecordExample example = new TIrisUserTaskRecordExample();
            example.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                    .andPropertyEqualTo(TIrisUserTaskRecordExample.TASK_ID, taskDTO.getBizId())
                    .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                    .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
            example.setOrderByClause("create_time desc");
            List<TIrisUserTaskRecordDO> irisUserTaskRecordDOS = userTaskRecordMapper
                    .limitSelectByExample(example, 0, 1);
            //无论是否有任务进度记录,都检查该用户当前跑批是否可以参加活动任务
            ActivityCheckResultDTO checkResultDTO = getCheckResultDTO(pid, uid, timestamp, registGift,
                    registGiftActivityExecutor);

            if (CollectionUtils.isEmpty(irisUserTaskRecordDOS)) {
                //未参加注册有礼,构建任务参与记录跑批数据
                userTaskBatchDataDOS
                        .add(buildUserTaskBatchDataDOS(registGift, taskDTO, batchNo, nickName, traineeDateTime, uid,
                                pid, taskAwardInfoMap, checkResultDTO, "", timestamp));
            } else {
                TIrisUserTaskBatchDataVO dataDO = convertRecordDO2BatchDataDO(batchNo, nickName, traineeDateTime,
                        irisUserTaskRecordDOS.get(0), taskAwardInfoMap);
                //注册有礼周期为天,yyyy-MM-dd,跑批记录每个用户只能有一条,覆盖更新，设置周期为""
                dataDO.setTaskPeriod("");
                if (traineeDateTime != null) {
                    dataDO.setCurrentTaskStartTime(traineeDateTime);
                }
                handleAwardReceiveInfo(Lists.newArrayList(dataDO));
                userTaskBatchDataDOS.add(dataDO);
            }
        });

    }

    /**
     * 其他活动任务参与数据处理,升级有礼,注册有礼,按批次新增记录即可,统一批量入库
     *
     * @param batchNo
     * @param nickName
     * @param traineeDateTime
     * @param uid
     * @param userTaskBatchDataDOS
     * @param taskAwardInfoMap
     */
    private void handleOtherTaskData(String batchNo, String nickName, Date traineeDateTime,
            String uid, List<TIrisUserTaskBatchDataVO> userTaskBatchDataDOS,
            Map<String, AwardInfoDTO> taskAwardInfoMap, List<String> taskIds) {
        TIrisUserTaskRecordExample example = new TIrisUserTaskRecordExample();
        example.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyIn(TIrisUserTaskRecordExample.TASK_ID, taskIds)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        List<TIrisUserTaskRecordDO> irisUserTaskRecordDOS = userTaskRecordMapper.selectByExample(example);

        irisUserTaskRecordDOS
                .forEach(
                        task -> userTaskBatchDataDOS
                                .add(convertRecordDO2BatchDataDO(batchNo, nickName, traineeDateTime, task,
                                        taskAwardInfoMap)));

    }

    /**
     * 没有任务参与进度,新构建用户任务参与数据
     *
     * @param activity
     * @param task
     * @param batchNo
     * @param nickName
     * @param traineeTimeDate
     * @param uid
     * @param taskAwardInfoMap
     * @param checkResultDTO
     * @param period
     * @return
     */
    private TIrisUserTaskBatchDataVO buildUserTaskBatchDataDOS(ActivityDTO activity, ActivityTaskDTO task,
            String batchNo, String nickName,
            Date traineeTimeDate, String uid, String pid, Map<String, AwardInfoDTO> taskAwardInfoMap,
            ActivityCheckResultDTO checkResultDTO, String period, Long timestamp) {
        Date current = new Date();
        Date currentTaskStartTime = current;
        Date currentTaskEndTime = current;
        byte userTaskStatus = UserTaskStatusEnum.PROGRESS.getCode();
        byte estimateUserTaskStatus = TaskEstimateStatusEnum.PROGRESS.getCode();
        if (ActivityTypeEnum.INVITE_GIFT.getCode().equals(activity.getActivityType())) {
            //邀请有礼活动
            if (traineeTimeDate != null) {
                currentTaskStartTime = inviteCommissionTaskExecutor.initCurrentTaskStartTime(traineeTimeDate.getTime());
                currentTaskEndTime = inviteCommissionTaskExecutor.initCurrentTaskEndTime(traineeTimeDate.getTime());
            }
        } else if (ActivityTypeEnum.MONTH_GIFT.getCode().equals(activity.getActivityType())) {
            //月月领活动,开始时间默认给当月1号起始时间(归属月份用)
            LocalDate date = LocalDate.parse(batchNo, DateTimeFormatter.ofPattern(TimeUtils.YYYY_MM_DD));
            currentTaskStartTime = Date
                    .from(date.with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay().atZone(ZoneId.systemDefault())
                            .toInstant());
            currentTaskEndTime = Date.from(date.with(TemporalAdjusters.lastDayOfMonth()).atTime(23, 59, 59)
                    .atZone(ZoneId.systemDefault()).toInstant());
        } else if (ActivityTypeEnum.REGIST_GIFT.getCode().equals(activity.getActivityType())) {
            //注册有礼，活动开始时间为成为见习会员时间
            if (traineeTimeDate != null) {
                currentTaskStartTime = traineeTimeDate;
            }
        }

        //未参与的进度跑批记录,当前跑批时间已经超过了任务结束时间,状态默认为终态 未完成
        if (currentTaskEndTime.getTime() <= timestamp) {
            userTaskStatus = UserTaskStatusEnum.UNFINISHED.getCode();
            estimateUserTaskStatus = TaskEstimateStatusEnum.UNFINISHED.getCode();
        }

        TIrisUserTaskBatchDataVO taskBatchDataVO = new TIrisUserTaskBatchDataVO();
        taskBatchDataVO.setUserTaskRecordId(StrUtil.EMPTY);
        taskBatchDataVO.setSuperiorAreaId(0L);
        taskBatchDataVO.setAreaId(0L);
        taskBatchDataVO.setAdvisorUid(StrUtil.EMPTY);
        taskBatchDataVO.setUid(uid);
        taskBatchDataVO.setPid(pid == null ? "" : pid);
        taskBatchDataVO.setActivityId(activity.getBizId());
        taskBatchDataVO.setTaskId(task.getBizId());
        taskBatchDataVO.setActivityType(activity.getActivityType());
        taskBatchDataVO.setTaskPeriod(period);
        taskBatchDataVO.setUserTaskStatus(userTaskStatus);
        taskBatchDataVO.setEstimateUserTaskStatus(estimateUserTaskStatus);
        taskBatchDataVO.setEstimateCommission(0);
        taskBatchDataVO.setCommission(0);
        taskBatchDataVO.setGmv(0);
        taskBatchDataVO.setShareCount(0);
        taskBatchDataVO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.UNISSUED.getCode());
        taskBatchDataVO.setCreateTime(current);
        taskBatchDataVO.setUpdateTime(current);
        taskBatchDataVO.setCurrentTaskStartTime(currentTaskStartTime);
        taskBatchDataVO.setCurrentTaskEndTime(currentTaskEndTime);
        taskBatchDataVO.setPeriodType(activity.getPeriodType());
        taskBatchDataVO.setExtInfo("");
        taskBatchDataVO.setBatchNo("");
        taskBatchDataVO.setNickName(nickName == null ? "" : nickName);
        taskBatchDataVO.setTraineeTime(traineeTimeDate == null ? DateUtil.date(0L) : traineeTimeDate);
        taskBatchDataVO.setAwardSendTime(current);
        taskBatchDataVO.setAwardType(taskAwardInfoMap.get(task.getBizId()).getType());
        taskBatchDataVO.setAwardAmount(taskAwardInfoMap.get(task.getBizId()).getValue());
        taskBatchDataVO.setParticipable(checkResultDTO.isSatisfy() ? TaskBatchDateParticipableEnum.YES.getCode()
                : TaskBatchDateParticipableEnum.NO.getCode());
        taskBatchDataVO
                .setRemark(StringUtils.isEmpty(checkResultDTO.getErrorMsg()) ? "" : checkResultDTO.getErrorMsg());
        //没有实际任务进度,系统自动生成的跑批数据,未参加活动
        taskBatchDataVO.setIsParticipated(TaskBatchDateIsParticipatedEnum.NO.getCode());
        taskBatchDataVO.setAwardInfo(JSONObject.toJSONString(taskAwardInfoMap.get(task.getBizId())));
        taskBatchDataVO.setPidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        taskBatchDataVO.setUidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        taskBatchDataVO.setTier(task.getTier());
        return taskBatchDataVO;
    }


    /**
     * 已有任务进度记录，转换为用户任务参与数据
     *
     * @param batchNo
     * @param nickName
     * @param traineeTime
     * @param taskRecordDO
     * @param taskAwardInfoMap
     * @return
     */
    private TIrisUserTaskBatchDataVO convertRecordDO2BatchDataDO(String batchNo, String nickName, Date traineeTime,
            TIrisUserTaskRecordDO taskRecordDO,
            Map<String, AwardInfoDTO> taskAwardInfoMap) {
        TIrisUserTaskBatchDataVO batchDataVO = BeanConvertUtil.INSTANCE.convertTaskRecordDO2BatchDataVO(taskRecordDO);
        batchDataVO.setBatchNo("");
        batchDataVO.setOrderFinishTime(taskRecordDO.getOrderFinishTime());
        batchDataVO.setNickName(nickName == null ? "" : nickName);
        batchDataVO.setTraineeTime(traineeTime == null ? DateUtil.date(0l) : traineeTime);
        batchDataVO.setAwardType(taskAwardInfoMap.get(taskRecordDO.getTaskId()).getType());
        batchDataVO.setAwardAmount(taskAwardInfoMap.get(taskRecordDO.getTaskId()).getValue());
        batchDataVO.setParticipable(TaskBatchDateParticipableEnum.YES.getCode());
        batchDataVO.setIsParticipated(taskRecordDO.getIsParticipated());
        batchDataVO.setUserTaskRecordId(taskRecordDO.getBizId());
        batchDataVO.setAwardInfo(JSONObject.toJSONString(taskAwardInfoMap.get(taskRecordDO.getTaskId())));
        batchDataVO.setRemark("");
        batchDataVO.setAwardSendTime(DateUtil.date(0l));
        batchDataVO.setPidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        batchDataVO.setUidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        batchDataVO.setSuperiorAreaId(0l);
        batchDataVO.setAreaId(0l);
        batchDataVO.setAdvisorUid(StrUtil.EMPTY);
        batchDataVO.setInviteLimit(taskRecordDO.getInviteLimit());
        batchDataVO.setInviteSeq(taskRecordDO.getInviteSeq());
        if (TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode() == taskRecordDO.getAwardIssueStatus()) {
            //进度记录是已发放成功,查询奖品发奖记录,获取奖品发放时间
            TIrisActivityAwardRecordExample example = new TIrisActivityAwardRecordExample();
            example.createCriteria().andPropertyEqualTo(TIrisActivityAwardRecordExample.UID, taskRecordDO.getUid())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.ACTIVITY_ID, taskRecordDO.getActivityId())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.TASK_ID, taskRecordDO.getTaskId())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.ISSUE_STATUS,
                            AwardRecordIssueStatusEnum.ISSUE_SUCCEED.getCode())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.SHARDING_ID,
                            ShardingIdUtil.sharding(taskRecordDO.getUid()));
            example.setOrderByClause(" id desc ");
            List<TIrisActivityAwardRecordDO> awardRecordDOS = activityAwardRecordMapper
                    .limitSelectByExample(example, 0, 1);
            if (!CollectionUtils.isEmpty(awardRecordDOS)) {
                TIrisActivityAwardRecordDO awardRecordDO = awardRecordDOS.get(0);
                batchDataVO.setAwardSendTime(
                        Optional.ofNullable(awardRecordDO.getCreateTime()).orElseGet(() -> DateUtil.date(0l)));
                //获取外部单号
                JSONObject extInfo = JSON.parseObject(awardRecordDO.getExtInfo());
                String outTradeNo = Optional.ofNullable(extInfo)
                        .map(i -> i.getString("outTradeNo")).orElse(null);
                if (StrUtil.isNotBlank(outTradeNo)) {
                    batchDataVO.setOutTradeNo(outTradeNo);
                }
            }
        }
        return batchDataVO;
    }

    private Date traineeTimeTo29(Date becomeTraineeTime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(becomeTraineeTime);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.add(Calendar.DATE, 29);
        return cal.getTime();
    }

}
